﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Data;
using System.Xml;
using System.IO;

namespace TED
{
    public class MetalinkConverter
    {
        public MetalinkConverter()
        {
        }

        #region - Private variables -
        DataTable convertedData = null;
        DataSet talkData = null;
        private bool lastNodeWasUrl = false;
        DataRow currentRow = null;
        #endregion

        #region - Convert Metalink File -
        private void loadDoc(string filePath)
        {
            XmlDocument rawData = new XmlDocument();
            loadDTSchema();
            rawData.Load(filePath);
            recurseNodes(rawData.DocumentElement);
        }
        private void loadDTSchema()
        {
            convertedData = new DataTable();
            convertedData.Columns.Add(FieldNames.Theme);
            convertedData.Columns.Add(FieldNames.Name);
            convertedData.Columns.Add(FieldNames.URL);
            convertedData.Columns.Add(FieldNames.Year, typeof(int));
        }
        private void recurseNodes(XmlNode node)
        {
            var sb = new StringBuilder();
            //start recursive loop with level 0 
            recurseNodes(node, 0, sb);
        }
        private void recurseNodes(XmlNode node, int level, StringBuilder sb)
        {
            //TODO: When importing, make hash value on the name for primary key
            if (lastNodeWasUrl && node.Value.EndsWith(".mp4"))
            {
                //sb.AppendLine(node.Value);
                //sb.AppendLine();
                addUrlAndDate(node.Value);
                convertedData.Rows.Add(currentRow);
            }
            lastNodeWasUrl = node.Name == "url";
            if(node.Attributes != null)
            foreach (XmlAttribute attr in node.Attributes)
            {
                if (node.Name == "file" && attr.Name == "name" && attr.Value.EndsWith(".mp4"))
                {
                    currentRow = convertedData.NewRow();
                    addThemeAndName(attr.Value);
                    //sb.AppendLine(attr.Value);
                }
            }
            if (node.ChildNodes != null)
            foreach (XmlNode n in node.ChildNodes)
            {
                recurseNodes(n, level + 1, sb);
            }
        }
        private void addUrlAndDate(string value)
        {
            string[] values = value.Split('_');
            currentRow[FieldNames.URL] = value;
            int year = 0;
            if(values.Length > 1)
                year = Convert.ToInt32(values[values.Length -1].Substring(0, 4));
            currentRow[FieldNames.Year] = year;
        }
        private void addThemeAndName(string value)
        {
            string[] values = value.Split('/');
            currentRow[FieldNames.Theme] = values[0];
            currentRow[FieldNames.Name] = values[1];
        }
        #endregion

        #region - Initialize DataSet -
        private void initializeDataSet()
        {
            talkData = new DataSet("talkData");
            loadThemesSchema();
            loadThemes();
            loadTalksSchema();
            loadTalks();
            DataRelation dr = new DataRelation(DataRelations.themesToTalks, talkData.Tables[TableNames.themes].Columns[FieldNames.ThemeId], talkData.Tables[TableNames.talks].Columns[FieldNames.ThemeId]);
            talkData.Relations.Add(dr);
        }
        private void loadThemesSchema()
        {
            DataTable themes = new DataTable("themes");
            DataColumn dc = themes.Columns.Add(FieldNames.ThemeId, typeof(int));
            dc.AutoIncrement = true;
            dc.AutoIncrementSeed = 1;
            dc.AutoIncrementStep = 1;
            themes.PrimaryKey = new DataColumn[] { dc };
            themes.Columns.Add(FieldNames.Theme);
            talkData.Tables.Add(themes);
        }
        private void loadTalksSchema()
        {
            DataTable talks = new DataTable(TableNames.talks);
            DataColumn tmp;
            
            talks.Columns.Add(FieldNames.Name);
            talks.Columns.Add(FieldNames.URL);
            talks.Columns.Add(FieldNames.Year, typeof(int));
            talks.Columns.Add(FieldNames.ThemeId, typeof(int));
            tmp = talks.Columns.Add(FieldNames.Status, typeof(int));
            tmp.DefaultValue = 0;
            talkData.Tables.Add(talks);
        }
        private void loadThemes()
        {
            DataView dv = new DataView(convertedData);
            DataTable uniqueThemes = dv.ToTable(true, FieldNames.Theme);
            DataTable themes = talkData.Tables[TableNames.themes];

            foreach (DataRow dr in uniqueThemes.Rows)
            {
                DataRow theme = themes.NewRow();
                theme[FieldNames.Theme] = dr[FieldNames.Theme];
                themes.Rows.Add(theme);
            }
        }
        private void loadTalks()
        {
            DataRow [] rawData;
            DataRow newTalk;
            string query;
            foreach (DataRow theme in talkData.Tables[TableNames.themes].Rows)
            {
                query = FieldNames.Theme + " = '" + theme[FieldNames.Theme]+"'";
                rawData = convertedData.Select(query);
                foreach (DataRow raw in rawData)
                {
                    newTalk = talkData.Tables[TableNames.talks].NewRow();
                    newTalk[FieldNames.Name] = raw[FieldNames.Name];
                    newTalk[FieldNames.URL] = raw[FieldNames.URL];
                    newTalk[FieldNames.Year] = raw[FieldNames.Year];
                    newTalk[FieldNames.ThemeId] = theme[FieldNames.ThemeId];
                    talkData.Tables[TableNames.talks].Rows.Add(newTalk);
                }
            }
        }
        #endregion

        #region - Public properties / variables -
        #endregion

        #region - Public methods -
        public void ConvertMetaDataFile(string metaLinkFile,string outputPath)
        {
            if (File.Exists(metaLinkFile) && Directory.Exists(outputPath))
            {
                loadDoc(metaLinkFile);
                initializeDataSet();
                DataSaver.SaveDataSet(talkData,outputPath);
            }
        }
        #endregion
    }
}
